/* This class is a custom editor, not that it should be put in a /Editor folder in the Assets folder of the project
 * 
 * It provides an easy to use interface for gamedesigners to design the stats a gameObject should contain. as long as
 * its put into a /Editor folder, it automaticly changes the Inspector GUI for the CharacterStats class.
 *
 * The CharacterStatsEditor automatically adds and removes Stat components and makes sure they are referenced in the
 * CharacterStats class.
 *
 * Author : Reinier
 */

@CustomEditor(CharacterStats)

class CharacterStatsEditor extends Editor {

private var folded : boolean; /* A boolean to track if the customstats editors should be folded or not */

	/* The OnInspectorGUI() method is called every frame as long as the inspector is enabled in the editor */
	function OnInspectorGUI() {
	
		/* provides two input fields for int, for base health and current health */
		var setAmount : int;
		var setGrowth : float;
		target.baseHealth = EditorGUILayout.IntField("Base Health", target.baseHealth);
		target.currentHealth = EditorGUILayout.IntField("Current Health", target.currentHealth);
		
		/* If the target is an enemy, also provide a field for setting the experience granted to the killer when it dies */
		if("Enemy" == target.gameObject.tag) {
			target.xpValue = EditorGUILayout.IntField("XP worth", target.xpValue);
		}
				
		/* provides a toggle button for adding the vitality standard stat */
		target.hasVitality = EditorGUILayout.Toggle("Has Vitality", target.hasVitality);
		
		/* If the vitality toggle has been enabled, also enable the editors for it's variables */		
		if(target.hasVitality) {
			/* if there is no vitality Stat component added yet, do so first */
			if(!target.vitality) {
				target.vitality = target.gameObject.AddComponent("Stat");
				target.vitality.SetName("Vitality");
				target.vitality.SetBase(5);
				target.vitality.SetGrowth(1.2);;
				}
			
			/* provides an input field for setting the base amount, and updates the actual value */
			setAmount = target.vitality.GetBase();
			setAmount = EditorGUILayout.IntField("Base amount", setAmount);
			target.vitality.SetBase(setAmount);
			
			/* provides an input field for setting the growth factor, and updates the actual value */
			setGrowth = target.vitality.GetGrowth();
			setGrowth = EditorGUILayout.FloatField("Growth Value", setGrowth);
			target.vitality.SetGrowth(setGrowth);
			
		}
		
		/* When the vitality toggle is disabled, the vitality Stat component is destroyed if one exists */
		if(!target.hasVitality) {
			if(target.vitality) {
				DestroyImmediate(target.vitality, true);
			}
		}
		
		/* provides a toggle button for adding the defence standard stat */
		target.hasDefence = EditorGUILayout.Toggle("Has Defence", target.hasDefence);
		
		/* If the defence toggle has been enabled, also enable the editors for it's variables */
		if(target.hasDefence) {
			/* if there is no defence Stat component added yet, do so first */
			if(!target.defence) {
				target.defence = target.gameObject.AddComponent("Stat");
				target.defence.SetName("Defence");
				target.defence.SetBase(5);
				target.defence.SetGrowth(1.3);
			}
			
			/* provides an input field for setting the base amount, and updates the actual value */
			setAmount = target.defence.GetBase();
			setAmount = EditorGUILayout.IntField("Base amount", setAmount);
			target.defence.SetBase(setAmount);
			
			/* provides an input field for setting the growth factor, and updates the actual value */
			setGrowth = target.defence.GetGrowth();
			setGrowth = EditorGUILayout.FloatField("Growth Value", setGrowth);
			target.defence.SetGrowth(setGrowth);
		}
		
		/* When the defence toggle is disabled, the defence Stat component is destroyed if one exists */
		if(!target.hasDefence) {
			if(target.defence) {
				DestroyImmediate(target.defence, true);
			}
		}

		/* provides a toggle button for adding the attack standard stat */
		target.hasAttack = EditorGUILayout.Toggle("Has Attack", target.hasAttack);
		
		/* If the attack toggle has been enabled, also enable the editors for it's variables */
		if(target.hasAttack) {
			/* if there is no attack Stat component added yet, do so first */
			if(!target.attack) {
				target.attack = target.gameObject.AddComponent("Stat");
				target.attack.SetName("Attack");
				target.attack.SetBase(5);
				target.attack.SetGrowth(1.4);
			}
			
			/* provides an input field for setting the base amount, and updates the actual value */
			setAmount = target.attack.GetBase();
			setAmount = EditorGUILayout.IntField("Base amount", setAmount);
			target.attack.SetBase(setAmount);
			
			/* provides an input field for setting the growth factor, and updates the actual value */
			setGrowth = target.attack.GetGrowth();
			setGrowth = EditorGUILayout.FloatField("Growth Value", setGrowth);
			target.attack.SetGrowth(setGrowth);
		}

		/* When the attack toggle is disabled, the attack Stat component is destroyed if one exists */
		if(!target.hasAttack) {
			if(target.attack) {
				DestroyImmediate(target.attack, true);
			}
		}

		/* Adds a space between the standard stat editors and the custom editors for aesthetic purposes */
		EditorGUILayout.Space();
		
		/* All custom Stats should be put into the array, but since the array will be re-initiated each frame
		 * a temporary array must also be created to transfer all the values in the old array into the new one and
		 * keep the array null-value free
		 */
		
		
		/* Creates a button in the inspector for adding a new custom stat */
		if(GUILayout.Button("Add Custom Stat")) {
			/* The number of stats variable will be increased so the inspector knows how large the array needs to be */
			target.numberOfCustomStats = target.numberOfCustomStats + 1;
		}

		/* As long as there are one or more custom stats, a new array should be made */
		if(target.numberOfCustomStats > 0) {
			/* Creates a temporary array to hold any values that need to be preserved */
			var tempArray : Stat[] = new Stat[target.numberOfCustomStats];
			
			/* A temporary int value to cycle through the temporary array during the for loop */
			var counter : int = 0;
			/* The for loop cycles through every value contained in the old array, any null values are not copied into the temporary array */
			for(i = 0; i < target.customStatArr.length; i++) {
				if(target.customStatArr[i]) {
					tempArray[counter] = target.customStatArr[i];
					counter ++;
				}
			}		
		    
		    /* if the last entry in the temporary array is still null it means numberOfCustomStats is increased and thus
		     * it means a new custom stat has been added
		     */
			if(!tempArray[target.numberOfCustomStats-1]) {
					/* Add a new custom stat with standard values */
					tempArray[target.numberOfCustomStats-1] = target.gameObject.AddComponent("Stat");
					tempArray[target.numberOfCustomStats-1].SetName("Custom Stat");
					tempArray[target.numberOfCustomStats-1].SetBase(5);
					tempArray[target.numberOfCustomStats-1].SetGrowth(1);
			}
			
			/* Recreate the old array to fit the new number of stats */
			target.customStatArr = new Stat[target.numberOfCustomStats];
			
			/* Creates a foldout button for any custom stats */
			folded = EditorGUILayout.Foldout(folded, "Custom Stats");
						
			/* Loop through the new array and copy the values from the temporary array */
			for(i = 0; i<target.customStatArr.length; i++) {
				/* Copy the value from the temporary array */
				target.customStatArr[i] = tempArray[i];
		
				/* Only display the values in the custom stats when the foldout toggle is enabled */
				if(folded) {
					var tempStat : Stat = target.customStatArr[i];
				
					var setterName : String = target.customStatArr[i].GetName();
					var setterAmount : int = target.customStatArr[i].GetBase();
					var setterGrowth : float = target.customStatArr[i].GetGrowth();
				
					/* Creates fields for the values to be edited and updates their actual values*/
					setterName = EditorGUILayout.TextField("Stat Name", setterName);
					tempStat.SetName(setterName);
					setterAmount = EditorGUILayout.IntField("Base amount", setterAmount);
					tempStat.SetBase(setterAmount);
					setterGrowth = EditorGUILayout.FloatField("Growth Value", setterGrowth);
					tempStat.SetGrowth(setterGrowth);
				
					target.customStatArr[i] = tempStat;
				
					/* Creates a button to remove the Stat component from the gameobject
					 * The array will hold a null value which will be filtered out next frame
					 */
					if(GUILayout.Button("Remove this stat")) {
						DestroyImmediate(target.customStatArr[i], true);
						target.numberOfCustomStats = target.numberOfCustomStats - 1;
					}
				}
			}
		}

		/* When a change is made the SetDirty flag is enabled so the changes will be saved to disk */
		if (GUI.changed) {
       	 EditorUtility.SetDirty(target);
        }
	}
}
